/**
 * ClientController.h
 *
 *  Created on: 2009-04-17
 *      Author: Jacek Suchowski
 *
 * Implementacja klasy odpowieadająca za komunikację z klientem w osobnym wątku
 */

#include "ClientController.h"
#include "structures.h"
#include "ServerThread.h"
#include "messages/MessageExecutor.h"
#include "messages/MessageRRQ.h"
#include "messages/MessageWRQ.h"
#include "messages/MessageDataPackage.h"
#include "messages/MessageACK.h"
#include "messages/MessageError.h"
#include "Log.h"
#include <iostream>
#include <stdlib.h>


using namespace std;

namespace tftp_server
{


ClientController::ClientController()
{
	;
}

ClientController::ClientController(bool arg, int socket_, struct sockaddr_in newClientName_, Package firstPackage_, MacCollector *ptr_)
{

	if (arg == true)
	{
		ClientControllerArguments args;
		args.socket = socket_;
		args.newClientName = newClientName_;
		args.package = firstPackage_;
		args.ptr = ptr_;
		threadHandle = pthread_create(&threadId, NULL, &runFunc, &args);
		sleep(1);
	}
}

ClientController::~ClientController()
{
	;
}


void *ClientController::runFunc(void * args)
{
	ClientControllerArguments temp = *((ClientControllerArguments*) (args));
	ClientController cc;
	cc.run(temp.socket, temp.newClientName, temp.package, temp.ptr);
	return NULL;
}





void ClientController::run(int socket_, struct sockaddr_in newClientName_, Package firstPackage, MacCollector *ptr_)
{
	socket = socket_;
	newClientName = newClientName_;
	package = firstPackage;
	ptr = ptr_;
	MessageExecutor *message;

	while (1)
	{

		switch (package.opcode[1])
		{
		case 1:
			for(int i=0; i<256; i++)
			{
				fileName[i] = package.filename[i];
				mode[i] = package.mode[i];
			}
			message = new MessageRRQ(this, package);
			message->execute();
			delete message;
			break;
		case 2:
			message = new MessageWRQ(this, package);
			message->execute();
			delete message;
			Loger::getInstance().send(Log("ClientController: WRQ request not permitted!", 3));
			exit(-1);
			break;
		case 3:
			message = new MessageDataPackage(this, package);
			message->execute();
			delete message;
			Loger::getInstance().send(Log("ClientController: DATA request not permitted!", 3));
			exit(-1);
			break;
		case 4:
			message = new MessageACK(this, package);
			message->execute();
			delete message;
			break;
		case 5:
			message = new MessageError(this, package);
			message->execute();
			delete message;
			break;
		default:
			Loger::getInstance().send(Log("ClientController: Receive bad package !", 2));
			exit(-1);
			break;

		}
		package = ServerThread::getInstance().receivePackage(socket, newClientName);
	}
}


	void ClientController::send(Package package)
	{
		ServerThread::getInstance().sendPackage(package, socket, newClientName);

	}

	MAC ClientController::findMac(IP ip)
	{
		return ptr->findMac(ip);
	}

	void ClientController::exit(int status)
	{
		if(status >= 0)
			Loger::getInstance().send(Log("ClientController: Exit thread with 0 status!", 3));
		else
			Loger::getInstance().send(Log("ClientController: Exit thread with -1 status!", 1));
		close(socket);
		pthread_exit(&status);;
	}

	char* ClientController::getFileName()
	{
		return fileName;
	}

	string ClientController::getIp() const
	{
		string ret(inet_ntoa(newClientName.sin_addr));
		return ret;
	}

	int ClientController::getNextBlockNumber() const
	{
		return nextBlockNumber;
	}

	void ClientController::setNextBlockNumber(int nextblocknumber_)
	{
		nextBlockNumber = nextblocknumber_;
	}

	int ClientController::getLastSend() const
	{
		return lastSend;
	}

	void ClientController::setLastSend(int lastSend)
	{
		lastSend = lastSend;
	}

	char* ClientController::getMode()
	{
		return mode;
	}

}
